<script setup lang="ts">
import { computed, onMounted, ref, shallowRef } from 'vue';
import TypeIt from 'typeit';
import { useAppStore } from '@/store/modules/app';
import { useThemeStore } from '@/store/modules/theme';
import PwdLogin from './modules/pwd-login.vue';
import Register from './modules/register.vue';
import ResetPwd from './modules/reset-pwd.vue';

const appStore = useAppStore();
const themeStore = useThemeStore();
const currentModule = ref<'pwd-login' | 'register' | 'reset-pwd'>('pwd-login');

const moduleMap = {
  'pwd-login': { label: '密码登录', component: PwdLogin },
  register: { label: '注册账号', component: Register },
  'reset-pwd': { label: '重置密码', component: ResetPwd }
};

const activeModule = computed(() => moduleMap[currentModule.value]);

function switchModule(module: 'pwd-login' | 'register' | 'reset-pwd') {
  currentModule.value = module;
}

const titleRef = shallowRef();

// 打字机效果初始化
function initTypeIt() {
  if (!titleRef.value) return;
  const typeItInstance = new TypeIt(titleRef.value, {
    strings: 'GameStoreX',
    lifeLike: true,
    speed: 100,
    loop: false
  });
  typeItInstance.go();
}

onMounted(() => {
  initTypeIt();
  // 贪吃蛇演示初始化
  setTimeout(() => {
    const canvas = document.getElementById('snake-demo-canvas') as HTMLCanvasElement;
    if (!canvas) return;
    const ctx = canvas.getContext('2d')!;
    const w = canvas.width;
    const h = canvas.height;
    const grid = 16;
    const maxX = Math.floor(w / grid);
    const maxY = Math.floor(h / grid);
    const snake: { x: number; y: number }[] = [
      { x: 5, y: 5 },
      { x: 4, y: 5 },
      { x: 3, y: 5 }
    ];
    let dir = 'right';
    let food = { x: 10, y: 5 };
    function drawCell(x: number, y: number, color: string) {
      ctx.fillStyle = color;
      ctx.fillRect(x * grid + 2, y * grid + 2, grid - 4, grid - 4);
    }
    function draw() {
      ctx.clearRect(0, 0, w, h);
      // 画蛇
      snake.forEach((s, i) => drawCell(s.x, s.y, i === 0 ? '#a855f7' : '#6366f1'));
      // 画食物
      drawCell(food.x, food.y, '#22d3ee');
    }
    function getNextDir(head: { x: number; y: number }, curDir: string) {
      // 不能直接反向
      const opposites: Record<string, string> = { right: 'left', left: 'right', up: 'down', down: 'up' };
      const dirs = ['right', 'down', 'left', 'up'];
      // 计算朝向果实的优先级
      const priorities: string[] = [];
      if (food.x > head.x) priorities.push('right');
      if (food.x < head.x) priorities.push('left');
      if (food.y > head.y) priorities.push('down');
      if (food.y < head.y) priorities.push('up');
      // 补全其他方向
      dirs.forEach(d => {
        if (!priorities.includes(d)) priorities.push(d);
      });
      // 过滤掉直接反向
      const validDirs = priorities.filter(d => d !== opposites[curDir]);
      // 过滤掉撞墙和撞到自己
      const safeDirs = validDirs.filter(d => {
        let tx = head.x;
        let ty = head.y;
        if (d === 'right') tx += 1;
        if (d === 'left') tx -= 1;
        if (d === 'up') ty -= 1;
        if (d === 'down') ty += 1;
        // 撞墙
        if (tx < 0 || tx >= maxX || ty < 0 || ty >= maxY) return false;
        // 撞自己
        if (snake.some((s, i) => i < snake.length - 1 && s.x === tx && s.y === ty)) return false;
        return true;
      });
      return safeDirs[0] || curDir;
    }
    // 生成不与蛇重叠的果实位置
    function getNewFood(): { x: number; y: number } {
      for (let i = 0; i < 1000; i += 1) {
        const fx = Math.floor(Math.random() * (maxX - 2)) + 1;
        const fy = Math.floor(Math.random() * (maxY - 2)) + 1;
        const conflict = snake.some(s => s.x === fx && s.y === fy);
        if (!conflict) return { x: fx, y: fy };
      }
      // fallback
      return { x: 1, y: 1 };
    }
    function move() {
      const head = { ...snake[0] };
      dir = getNextDir(head, dir);
      if (dir === 'right') head.x += 1;
      if (dir === 'left') head.x -= 1;
      if (dir === 'up') head.y -= 1;
      if (dir === 'down') head.y += 1;
      // 吃到食物
      if (head.x === food.x && head.y === food.y) {
        snake.unshift(head);
        // 生长
        food = getNewFood();
      } else {
        snake.pop();
        snake.unshift(head);
      }
    }
    setInterval(() => {
      move();
      draw();
    }, 120);
    draw();
  }, 300);
});
</script>

<template>
  <div class="login-bg-gradient">
    <div class="login-container">
      <!-- 左侧轮播图 -->
      <div class="banner-area">
        <div class="carousel-card">
          <NCarousel autoplay :autoplay-interval="2500" show-arrow class="carousel-box">
            <img v-for="i in 3" :key="i" :src="`/banner/slide${i}.png`" class="banner-img" />
          </NCarousel>
        </div>
        <div class="snake-demo-card">
          <canvas id="snake-demo-canvas" width="480" height="240"></canvas>
        </div>
      </div>
      <!-- 右侧登录框 -->
      <div class="login-card">
        <NCard :bordered="false" class="card-inner relative w-full rd-12px">
          <div class="mx-auto h-full w-96 flex flex-col justify-center lt-sm:w-80">
            <header class="flex-y-center justify-between">
              <SystemLogo class="text-64px text-primary lt-sm:text-48px" />
              <h3 ref="titleRef" class="typeit-title"></h3>
              <div class="i-flex-col">
                <ThemeSchemaSwitch
                  :theme-schema="themeStore.themeScheme"
                  :show-tooltip="false"
                  class="text-20px lt-sm:text-18px"
                  @switch="themeStore.toggleThemeScheme"
                />
                <LangSwitch
                  v-if="themeStore.header.multilingual.visible"
                  :lang="appStore.locale"
                  :lang-options="appStore.localeOptions"
                  :show-tooltip="false"
                  @change-lang="appStore.changeLocale"
                />
              </div>
            </header>
            <main class="flex flex-col flex-1 justify-center pt-24px">
              <h3 class="text-18px text-primary font-medium">{{ activeModule.label }}</h3>
              <div class="pt-24px">
                <Transition name="fade" mode="out-in" appear>
                  <KeepAlive>
                    <component :is="activeModule.component" @switch="switchModule" />
                  </KeepAlive>
                </Transition>
              </div>
            </main>
          </div>
        </NCard>
      </div>
    </div>
  </div>
</template>

<style scoped>
/*
  请在 public/index.html 的 <head> 中添加：
  <link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@700&display=swap" rel="stylesheet">
*/
.login-bg-gradient {
  min-height: 100vh;
  width: 100vw;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(120deg, #3b82f6 0%, #22d3ee 30%, #34d399 65%, #6366f1 100%);
  background-size: 300% 300%;
  animation: gradientMove 3.5s cubic-bezier(0.4, 0.7, 0.6, 1) infinite alternate;
}
@keyframes gradientMove {
  0% {
    background-position: 0% 60%;
  }
  30% {
    background-position: 40% 40%;
  }
  60% {
    background-position: 70% 70%;
  }
  100% {
    background-position: 100% 40%;
  }
}
.login-container {
  display: flex;
  align-items: center;
  justify-content: center;
  max-width: 1500px;
  width: 100%;
  height: 560px;
  gap: 48px;
}
.banner-area {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  background: transparent;
  box-shadow: none;
  border-radius: 0;
  width: auto;
  height: auto;
  gap: 32px;
}
.carousel-card {
  background: rgba(255, 255, 255, 0.95);
  border-radius: 24px;
  box-shadow: 0 8px 32px rgba(99, 102, 241, 0.12);
  overflow: hidden;
  max-width: 480px;
  width: 100%;
  margin-bottom: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}
.banner-img {
  display: block;
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
  border-radius: 0;
  box-shadow: none;
  margin: 0 auto;
  background: transparent;
}
.banner-mask {
  display: none;
}
.login-card {
  min-width: 340px;
  max-width: 440px;
  width: 100%;
  height: 600px;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 8px 32px rgba(99, 102, 241, 0.12);
  background: rgba(255, 255, 255, 0.95);
  border-radius: 24px;
}
.card-inner {
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  background: transparent;
  box-shadow: none;
}
.snake-demo-card {
  width: 100%;
  max-width: 480px;
  height: 240px;
  background: rgba(255, 255, 255, 0.95);
  border-radius: 24px;
  box-shadow: 0 8px 32px rgba(99, 102, 241, 0.12);
  display: flex;
  align-items: center;
  justify-content: center;
  margin-top: 0;
  overflow: hidden;
  border: none;
}
.snake-demo-card canvas {
  background: #fff;
  border-radius: 16px;
  box-shadow: none;
}
.card-desc,
.brand {
  display: none;
}
.banner-stack {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
}
.carousel-box {
  width: 100%;
  max-width: 480px;
}
.typeit-title {
  font-family: 'Orbitron', 'Arial', sans-serif;
  font-size: 32px;
  letter-spacing: 2px;
  font-weight: 700;
  color: #223354;
  text-shadow: 0 2px 8px rgba(99, 102, 241, 0.1);
}
/* 登录、注册、重置密码等标题字体颜色 */
.login-card h3,
.card-inner h3 {
  color: #223354 !important;
}
/* 按钮主色调蓝色，hover加深 */
.n-button {
  background: #3b82f6 !important;
  color: #fff !important;
  border: none !important;
}
.n-button:hover {
  background: #2563eb !important;
}
@media (max-width: 900px) {
  .login-container {
    flex-direction: column;
    height: auto;
    gap: 24px;
    min-height: unset;
  }
  .banner-area,
  .login-card {
    height: auto;
    min-width: 0;
    max-width: 100vw;
  }
  .banner-img {
    height: auto;
  }
}
</style>
